package com.caimiao.miao.library.usb.accessory;

import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.lang.ref.WeakReference;

import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.os.ParcelFileDescriptor;
import android.util.Log;

import com.caimiao.miao.library.usb.interfaces.ICmdUtil;
import com.caimiao.miao.library.usb.logic.UsbScheduler;
import com.caimiao.miao.library.usb.interfaces.IUsbControl;
import com.caimiao.miao.library.usb.interfaces.IUsbReadCallback;
import com.caimiao.miao.library.usb.interfaces.IUsbTransfer;
import com.caimiao.miao.library.usb.interfaces.IUsbScheduler;
import com.caimiao.miao.library.utils.tip.ToastUtil;

public class UsbControl implements IUsbControl {
    private static final String TAG = "USBInterface";
    private static final String ACTION_USB_PERMISSION = "com.caimiao.miao.USB_PERMISSION";//package name

    protected static String ManufacturerString = "mManufacturer=FTDI";
    protected static String ModelString1 = "mModel=FTDIUARTDemo";
    protected static String ModelString2 = "mModel=FTDIUARTDemo";
    protected static String VersionString = "mVersion=1.0";

    protected UsbManager mUsbManager;
    protected PendingIntent mPermissionIntent;
    protected boolean mPermissionRequestPending = false;//是否申请过USB权限
    protected boolean isAccessoryAttached = false;//配件附加与否
    protected WeakReference<Context> mActivity;
    protected IUsbTransfer mUsbTransfer;//USB传输实现
    protected IUsbScheduler mUsbScheduler;//传输线程
    protected UsbDataBuffer mUsbDataBuffer;//数据缓存
    protected ICmdUtil mCmdUtil;

    private IUsbReadCallback iUsbReadCallback;


    private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            ToastUtil.show("action=" + action);
            if (ACTION_USB_PERMISSION.equals(action)) {
                synchronized (this) {
                    UsbAccessory accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        ToastUtil.show("允许USB许可");
                        OpenAccessory(accessory);
                    } else {
                        ToastUtil.show("没有权限的配件");
                        Log.d(TAG, "没有权限的配件: " + accessory);

                    }
                    mPermissionRequestPending = false;
                }
            } else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
                DestroyAccessory(true);
            } else {
                Log.d(TAG, "....");
            }
        }
    };

    public UsbControl(Context context) {
        mActivity = new WeakReference<>(context);
        //注册USB插拔监听广播
        mPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), 0);
        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
        filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
        filter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
        context.registerReceiver(mUsbReceiver, filter);

        //判断USB接口
        mUsbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
        UsbAccessory[] usbAccessory = mUsbManager.getAccessoryList();
        int length = usbAccessory == null ? 0 : usbAccessory.length;
        Log.e(TAG, "count = " + length);
        ToastUtil.show("Count = " + length);
        ///单片机型号判断，不同厂商不一样，由厂商提供
        for (int i = 0; i < length; i++) {
            UsbAccessory usb = usbAccessory[i];
            boolean model = "FTDIUARTDemo".equals(usb.getModel());
            boolean manufacturer = "FTDI`".equals(usb.getManufacturer());
            boolean version = "1.0".equals(usb.getVersion());
            ToastUtil.show("model: " + usb.getModel() + ", manufacturer: " + usb.getManufacturer() + ", version: " + usb.getVersion());
            Log.e(TAG, "model: " + model + ", manufacturer: " + manufacturer + ", version: " + version);
        }

        mUsbDataBuffer = new UsbDataBuffer();
    }

    @Override
    public void addUsbReadCallback(IUsbReadCallback iUsbReadCallback) {
        this.iUsbReadCallback = iUsbReadCallback;
    }

    @Override
    public void destroy() {
        if (mActivity.get() != null) {
            mActivity.get().unregisterReceiver(mUsbReceiver);
        }
        mUsbDataBuffer = null;
        DestroyAccessory(true);
    }

    @Override
    public void close(boolean isConfig) {
        DestroyAccessory(isConfig);
    }

    @Override
    public void setConfig(int baud, byte dataBits, byte stopBits, byte parity, byte flowControl) {
        if (mUsbTransfer != null)
            mUsbTransfer.setConfig(baud, dataBits, stopBits, parity, flowControl);
    }

    @Override
    public byte sendData(char[] value) {
        return mUsbTransfer.sendData(value);
    }

    @Override
    public int ResumeAccessory() {
        if (mUsbTransfer != null) return 1;

        UsbAccessory[] accessories = mUsbManager.getAccessoryList();
        if (accessories != null) {
            Log.d(TAG, "USB已插入");
        } else {
            Log.e(TAG, "USB未插入");
            isAccessoryAttached = false;
            return 2;
        }

        UsbAccessory accessory = (accessories == null ? null : accessories[0]);
        if (accessory != null) {
            if (-1 == accessory.toString().indexOf(ManufacturerString)) {
                ToastUtil.show("制造商不匹配");
                return 1;
            }

            if (-1 == accessory.toString().indexOf(ModelString1) && -1 == accessory.toString().indexOf(ModelString2)) {
                ToastUtil.show("模型不匹配");
                return 1;
            }

            if (-1 == accessory.toString().indexOf(VersionString)) {
                ToastUtil.show("版本不匹配");
                return 1;
            }
            ToastUtil.show("厂家、型号、版本匹配");
            isAccessoryAttached = true;

            if (mUsbManager.hasPermission(accessory)) {
                OpenAccessory(accessory);
            } else {
                synchronized (mUsbReceiver) {
                    if (!mPermissionRequestPending) {
                        ToastUtil.show("USB请求许可");
                        mUsbManager.requestPermission(accessory, mPermissionIntent);
                        mPermissionRequestPending = true;
                    }
                }
            }
        } else {
        }

        return 0;
    }

    protected void OpenAccessory(UsbAccessory accessory) {
        ParcelFileDescriptor mFileDescriptor = mUsbManager.openAccessory(accessory);
        if (mFileDescriptor != null) {
            FileDescriptor fd = mFileDescriptor.getFileDescriptor();
            FileInputStream mInputStream = new FileInputStream(fd);
            FileOutputStream mOutputStream = new FileOutputStream(fd);
            if (mInputStream == null || mOutputStream == null) {
                return;
            }

            if (mUsbTransfer == null)
                mUsbTransfer = new UsbTransfer(mFileDescriptor, mOutputStream, mInputStream, this);
            if (mUsbScheduler == null)
                mUsbScheduler = new UsbScheduler(this);
        }
    }

    protected void DestroyAccessory(boolean isConfig) {
        if (mUsbScheduler != null) mUsbScheduler.close();
        mUsbScheduler = null;
        if (mUsbTransfer != null) mUsbTransfer.close(isConfig);
        mUsbTransfer = null;
    }

    @Override
    public void callback(Command command) {
        if (iUsbReadCallback != null) iUsbReadCallback.call(command);
    }

    /***************************************数据缓存操作**************************************/

    @Override
    public void addCommandToWriteQueue(Command command) {
        if (mUsbDataBuffer != null) mUsbDataBuffer.addCommandToWriteQueue(command);
    }

    @Override
    public void addLastCmdToWriteQueue(Command command) {
        if (mUsbDataBuffer != null) mUsbDataBuffer.addLastCmdToWriteQueue(command);
    }

    @Override
    public Command nextCommand() {
        if (mUsbDataBuffer != null)
            return mUsbDataBuffer.nextCommand();
        return null;
    }

    @Override
    public void clearWriteQueue() {
        if (mUsbDataBuffer != null) mUsbDataBuffer.clearWriteQueue();
    }

    @Override
    public void setReadData(int count, byte[] usbData) {
        if (mUsbDataBuffer != null) mUsbDataBuffer.setReadData(count, usbData);
    }

    @Override
    public char[] getReadData() {
        if (mUsbDataBuffer != null)
            return mUsbDataBuffer.getReadData();
        return new char[0];
    }

    @Override
    public void clearReadData() {
        if (mUsbDataBuffer != null) mUsbDataBuffer.clearReadData();
    }
}